<!DOCTYPE HTML PUBLIC "HTML 4.01 Transitional">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>dragonfly.lsp</title>

<link rel="stylesheet" type="text/css" href="newlispdoc.css" />
</head>

<body style="margin: 20px;" text="#111111" bgcolor="#FFFFFF" 
			link="#376590" vlink="#551A8B" alink="#ffAA28">
<blockquote>
<center><h1>dragonfly.lsp</h1></center>
<p><a href="index.html">Module index</a></p><br/><h2>Module:&nbsp;dragonfly.lsp</h2><p>The heart of Dragonfly - A newLISP web framework for rapid web development.</p>
<b>Version: </b>0.70<br/>
<b>Author: </b>Team Dragonfly 2009<br/>
<b>Location: </b><a href="http://code.google.com/p/dragonfly-newlisp/">http://code.google.com/p/dragonfly-newlisp/</a><br/>
 <br>This file is the main entry-point of the Dragonfly framework and
 contains several important functions, as well as the default route
 definitions. The functions here are in the <tt>Dragonfly</tt> context (alias <tt>DF</tt>),
 which is the context your static files will be evaluated in by default.
 Therefore all of the functions here can be called in your templates without
 needing to be context-qualified.
 <br><br>Dragonfly's design is very simple, you can actually read through its
 source in very little time to get a great understanding of exactly how
 it works, and to get an idea of what sorts of tricks you can do to
 customize it to your liking (remember, newLISP is <em>extremely</em> dynamic!).
 <h3>The <tt>listener</tt> function</h3>
 The <tt>listener</tt> function is called in <tt>index.cgi</tt>. It is the function that
 kicks everything off by looping through the available routes, finding a
 match, running it, sending the output to the browser, and then exiting.
 <br><br>Before all of that, the very *first* thing it does is load the
 plugins in the <tt>dragonfly-framework/plugins-active</tt> folder, giving them
 an opportunity to do any special customization that they might require.
 <h3>Environment Variables</h3>
 At the very top of the <tt>config.lsp</tt> file there is the following line:
 <pre> (dolist (x (env)) (constant (global (sym (upper-case (first x)))) (last x)))</pre>
 This line simply loops through every environment variable and makes a
 global symbol out of it. This makes it extremely simple to access environment
 variables, simply type their name! If you prefer PHP-style, you can
 access them through the <tt>$SERVER</tt> function (simply a synonym for <tt>env</tt>).
 <br><br>To access any web parameters, files, and cookies use the functions <tt>$GET</tt>, <tt>$POST</tt>,
 <tt>$FILES</tt>, and <tt>$COOKIES</tt>, respectively. See <tt>Request.lsp</tt> for more information.
 <h3>Routes</h3>
 <p>Routes are FOOP objects inheriting from the Route class. They should have the <tt>Route.</tt> prefix.
 Currently they only need to support two functions: <tt>matches?</tt> and <tt>run</tt>.</p>
 <p>The listener loops through the available routes and calls <tt>matches?</tt> on them
 with no arguments. The route must decide, based on any data available to it,
 whether or not it to return a non-nil value from <tt>matches?</tt>.</p>
 Here, for example, is the <tt>matches?</tt> function for <tt>Route.Resource</tt>:
 <pre> (define (matches?)
     (when (regex {^([a-z]\w+)(/([a-z]\w+))?(/(\d+))?(\.([a-z]+))?} QUERY_STRING 1)
         (set 'resource_name $1 'resource_action $3 'resource_id $5 'response_format $7)
         (file? (set 'path (DF:resource-path resource_name)))
     )
 )
 </pre>
 There are two default routes: <tt>Route.Static</tt> and <tt>Route.Resource</tt>. See the
 documentation on the example-site and in <tt>config.lsp</tt> for more information on
 what they do.
 <h3>Resources</h3>
 <tt>Route.Resource</tt> handles URLs that refer to RESTful resources, represented as FOOP objects
 deriving from the <tt>Resource</tt> class. The resources reside in the <tt>RESOURCES_PATH</tt> as .lsp files.
 The URL scheme works in a similar manner to twitter's RESTful API:
 <pre>http://mysite.com/<em>resource</em>[/<em>action</em>][/<em>id</em>][.<em>response_format</em>][?get paramters...]</pre>
 <tt>resource</tt> maps to a context name in a special way. First <tt>Resource.</tt> is prepended
 to the name, then the underscores are removed and the name is written in title case.
 The <tt>resource</tt> may only have the letters A-Z (lowercase or uppercase), 0-9, the underscore,
 and it must begin with a letter.
 <br/><pre> my_resource => Resource.MyResource</pre>
 The name also maps to a real file located in <tt>RESOURCES_PATH</tt> by appending ".lsp" to the name:
 <br/><pre> my_resource => load file: RESOURCES_PATH/my_resource.lsp</pre>
 If <tt>resource</tt> implements <tt>action</tt>, then that function is called.
 Like <tt>resource</tt>, <tt>action</tt> may only contain letters, numbers, and the underscore.
 If no <tt>action</tt> is specified, then the resource's default function is called instead.
 If it is specified but no method of that name is found, <tt>catch-all</tt> will be called, which
 by default calls <tt>Dragonfly:die</tt>. You can override <tt>catch-all</tt> and do dispatch within
 it, as it takes the action name (as a string) as the first argument, followed by the
 <tt>id</tt> and the <tt>response_format</tt>.
 <p>The optional paramters <tt>id</tt> and <tt>response_format</tt> are passed in to the function
 as parameters (in that order, unless it is the <tt>catch-all</tt> function, in which case
 3 parameters are passed in as described above).</p>
 <p><tt>id</tt> may only contain numbers, and <tt>response_format</tt> may only contain letters.</p>
 <h3>Plugins</h3>
 There are two types of plugins, those in the <tt>plugins-active</tt> folder, and those
 in the <tt>plugins-inactive</tt> folder. The ones in the former are loaded when <tt>listener</tt>
 is called, prior to running the routes. Every .lsp file in the <tt>plugins-active</tt> folder
 is loaded at that point, so you'll only want your most frequently used files in there.
 <p>A good example of an active plugin is a custom route. Defining a custom route consists
 of two basic steps: creating your <tt>Route</tt> "subclass", and adding an instance of
 it to <tt>Dragonfly:dragonfly-routes</tt>. Take a look at how it's done in the source of
 <tt>dragonfly.lsp</tt> for more info.</p>
 <p>Inactive plugins are simply those that should be loaded on a "need to use" basis.
 Most plugins will probably fall into this category. Use <tt>Dragonfly:activate-plugin</tt>
 to load them. All plugins are loaded exactly once, no matter how many times
 <tt>activate-plugin</tt> is called on them.</p>








<br/><br/><center>- &sect; -</center><br/>
<a name="_DF_PAGE"></a><h3><font color=#CC0000>DF_PAGE</font></h3>
<b>syntax: DF_PAGE</b><br/>
 <p>The web-friendly, host-unqualified URL to the "current page"</p>
 <pre> ; load http://www.mysite.com/foo/bar?baz
 DF_PAGE ;=> "/foo/bar"
 ; load http://www.mysite.com
 DF_PAGE ;=> "/"</pre>

<br/><br/><center>- &sect; -</center><br/>
<a name="_DF_SELF"></a><h3><font color=#CC0000>DF_SELF</font></h3>
<b>syntax: DF_SELF</b><br/>
 <p>The full, local path (on the server) to the currently loaded file
 or view being displayed.</p>
 <b>example:</b>
 <pre> ; load http://www.mysite.com/foo/bar?baz
 DF_SELF ;=> "/home/www/mysite.com/foo/bar.html"</pre>
 <b>see:</b> the <tt>SET_DF_SELF</tt> function in utils.lsp for more info

<br/><br/><center>- &sect; -</center><br/>
<a name="_DF_SELF_DIR"></a><h3><font color=#CC0000>DF_SELF_DIR</font></h3>
<b>syntax: DF_SELF_DIR</b><br/>
 <p>The full, local path (on the server) to the directory holding
 the currently loaded file or view being displayed.</p>
 <b>example:</b>
 <pre> ; load http://www.mysite.com/foo/bar?baz
 DF_SELF_DIR ;=> "/home/www/mysite.com/foo"</pre>
 <b>see:</b> the <tt>SET_DF_SELF</tt> function in utils.lsp for more info




<br/><br/><center>- &sect; -</center><br/>
<a name="_STDOUT"></a><h3><font color=#CC0000>STDOUT</font></h3>
<b>syntax: STDOUT</b><br/>
 This is the buffer that contains the content that will get written
 to STDOUT if no errors are thrown. <tt>MAIN:print</tt> and <tt>MAIN:println</tt>
 are globally overridden to write to this buffer.
 Normally you should never need to modify this variable, however it is
 documented for reference's sake.





<br/><br/><center>- &sect; -</center><br/>
<a name="DF_activate-plugin"></a><h3><font color=#CC0000>DF:activate-plugin</font></h3>
<b>syntax: (<font color=#CC0000>DF:activate-plugin</font> <em>str-plugin-name</em> [<em>str-plugin-name-2</em> ...])</b><br/>
<b>parameter: </b><em>str-plugin-name</em> - The name of the plugin to load, without the ".lsp" extension.<br/>
 <br>Loads (once only) a the named plugin from the <tt>plugins-inactive</tt> folder.
 <br>If <em>str-plugin-name</em> refers to a directory, then loads all of the ".lsp" files in that directory.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_web-root"></a><h3><font color=#CC0000>DF:web-root</font></h3>
<b>syntax: (<font color=#CC0000>DF:web-root</font> [<em>str-path</em> [<em>bool-question-mark</em>]])</b><br/>
<b>parameter: </b><em>str-path</em> - Path relative to the folder containing <tt>index.cgi</tt>.<br/>
<b>parameter: </b><em>bool-question-mark</em> - Whether to return a URL with /? prepended.<br/>
 <p>This function is quite handy for making working links when your <tt>index.cgi</tt> file
 is not in <tt>DOCUMENT_ROOT</tt> but a subfolder of it.</p>
<b>example:</b><blockquote><pre> ; index.cgi is located in /home/user/site.com/examples-site
 ; Users visit http://www.site.com/example-site
 (web-root "about") =&gt; "/example-site/about"
 (web-root "/foo" true) =&gt; "/example-site/?foo"
 (web-root) =&gt; /example-site/</pre></blockquote>
<br/><br/><center>- &sect; -</center><br/>
<a name="DF_view-path"></a><h3><font color=#CC0000>DF:view-path</font></h3>
<b>syntax: (<font color=#CC0000>DF:view-path</font> <em>str-view-name</em>)</b><br/>
<b>parameter: </b><em>str-view-name</em> - Name of view in <tt>VIEWS_PATH</tt>, without any extension.<br/>
 <br>Returns the absolute path to the view as a string, appending <tt>VIEW_EXTENSION</tt> if necessary.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_partial-path"></a><h3><font color=#CC0000>DF:partial-path</font></h3>
<b>syntax: (<font color=#CC0000>DF:partial-path</font> <em>str-partial-name</em>)</b><br/>
 <br>Just like <tt>view-path</tt>, except for partials in <tt>PARTIALS_PATH</tt>.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_resource-path"></a><h3><font color=#CC0000>DF:resource-path</font></h3>
<b>syntax: (<font color=#CC0000>DF:resource-path</font> <em>str-resource-name</em>)</b><br/>
 <br>Similar to <tt>view-path</tt>, except for resources in <tt>RESOURCES_PATH</tt>.
 Don't include the .lsp extension.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_include"></a><h3><font color=#CC0000>DF:include</font></h3>
<b>syntax: (<font color=#CC0000>DF:include</font>)</b><br/>
 <br>Like <tt>display-file</tt> but does not pass the file through <tt>eval-template</tt>.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_display-file"></a><h3><font color=#CC0000>DF:display-file</font></h3>
<b>syntax: (<font color=#CC0000>DF:display-file</font>)</b><br/>
 <br>String-concats its arguments and displays the file
 at that path after passing it through <tt>eval-template</tt>.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_display-partial"></a><h3><font color=#CC0000>DF:display-partial</font></h3>
<b>syntax: (<font color=#CC0000>DF:display-partial</font> <em>str-partial-name</em>)</b><br/>
 Displays the partial named <em>str-partial-name</em> using <tt>display-file</tt> and <tt>partial-path</tt>.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_display-view"></a><h3><font color=#CC0000>DF:display-view</font></h3>
<b>syntax: (<font color=#CC0000>DF:display-view</font> <em>str-view-name</em>)</b><br/>
 Displays the view named <em>str-view-name</em> using <tt>display-file</tt> and <tt>view-path</tt>.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_display-error"></a><h3><font color=#CC0000>DF:display-error</font></h3>
<b>syntax: (<font color=#CC0000>DF:display-error</font> <em>int-error-code</em>)</b><br/>
 <br>Sends the <em>int-error-code</em> and, if it exists, displays the view named
 <em>int-error-code</em> using <tt>display-view</tt>. Otherwise, displays the built-in error
 template <tt>Dragonfly:ERROR_TEMPLATE</tt>.
<br/><br/>
 If an error is thrown with <tt>throw-error</tt>, this is automatically called
 with an <em>int-error-code</em> of 500 (Internal Server Error).

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_eval-template"></a><h3><font color=#CC0000>DF:eval-template</font></h3>
<b>syntax: (<font color=#CC0000>DF:eval-template</font> <em>str</em> [<em>ctx</em>])</b><br/>
<b>parameter: </b><em>str</em> - A string containing the template.<br/>
<b>parameter: </b><em>ctx</em> - Optional. Represents the context the template is evaluted in. Defaults to Dragonfly.<br/>
 <br>newLISP code in the template between the <tt>OPEN_TAG</tt> and <tt>CLOSE_TAG</tt> (see <tt>config.lsp</tt>) is
 evaluated, and the result, along with the text outside of the "code islands" will be sent if no errors occur.

<br/><br/><center>- &sect; -</center><br/>
<a name="DF_die"></a><h3><font color=#CC0000>DF:die</font></h3>
<b>syntax: (<font color=#CC0000>DF:die</font>)</b><br/>
 <br>String-concats its arguments, logs them as an error via <tt>log-err</tt>, and calls
 <tt>throw-error</tt> with the same string.
<br/><br/>
<b>see: </b>Dragonfly:display-error<br/>

















<br/><br/><center>- &part; -</center><br/>
<center><font face='Arial' size='-2' color='#444444'>
generated with <a href="http://newlisp.org">newLISP</a>&nbsp;
and <a href="http://newlisp.org/newLISPdoc.html">newLISPdoc</a>
</font></center>
</blockquote>
</body>
</html>
